package com.literature.search.file.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckRole;
import com.literature.search.core.common.MessageConstant;
import com.literature.search.core.entity.FileDocument;
import com.literature.search.core.entity.R.AjaxJson;
import com.literature.search.core.entity.dto.BasePageDTO;
import com.literature.search.file.service.IFileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Optional;

/**
 * @Author: DangKong
 * @Date: 2023/3/2 15:45
 * @Description:
 */

@Api(tags = "文件管理")
@RestController
@SaCheckLogin
@RequestMapping("files")
public class FileController {
    private final IFileService fileService;

    public FileController(IFileService fileService) {
        this.fileService = fileService;
    }


    /**
     * 表单上传文件
     * 当数据库中存在该md5值时，可以实现秒传功能
     */
    @ApiOperation(value = "PDF文件上传",notes = "只能上传PDF,100M以内" )
    @PostMapping("/upload")
    public AjaxJson fileUpload(@RequestParam("file") MultipartFile file) {
        return fileService.fileUpload(file);
    }


    @PostMapping("/listByPage")
    @SaCheckRole("admin")
    @ApiOperation(value = "分页查询",notes = "按上传时间降序,注意这个接口会返回所有的文件，包括索引未构建成功的" )
    public AjaxJson list(@ModelAttribute("pageParams") @Valid BasePageDTO pageParams){
        return fileService.listFilesByPage(pageParams);
    }

    @ApiOperation(value = "根据文件id查询文件信息",notes = "通过在url的路径上添加文件id即可" )
    @GetMapping("/queryById/{id}")
    public AjaxJson queryById(@PathVariable String id) {
        FileDocument fileDocument = fileService.queryById(id);
        if (fileDocument != null) {
            return AjaxJson.getSuccessData(fileDocument);
        } else {
            return AjaxJson.getSuccess(MessageConstant.FILE_NOT_FOUND);
        }
    }

    @GetMapping("/view/{id}")
    @ApiOperation(value = "预览整个文件",notes = "通过在url的路径上添加文件id即可" )
    public ResponseEntity<Object> serveFileOnline(@ApiParam(value = "文件id") @PathVariable String id) throws UnsupportedEncodingException {
        Optional<FileDocument> file = fileService.getById(id);
        if (file.isPresent()) {
            return ResponseEntity.ok()
                    // 这里需要进行中文编码
                    .header(HttpHeaders.CONTENT_DISPOSITION, "fileName=" + URLEncoder.encode(file.get().getFileName(), "utf-8"))
                    .header(HttpHeaders.CONTENT_TYPE, file.get().getContentType()) // 设置文件类型
                    .header(HttpHeaders.CONTENT_LENGTH, file.get().getSize() + "")
                    .header("Connection", "close") // 设置连接关闭
                    .body(file.get().getContent()); // 设置文件内容
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(MessageConstant.FILE_NOT_FOUND);
        }
    }

    @GetMapping("/downLoad/{id}")
    @ApiOperation(value = "下载文件",notes = "通过在url的路径上添加文件id即可")
    public ResponseEntity<Object> downloadFileById(@ApiParam("文件id") @PathVariable String id) throws UnsupportedEncodingException {
        Optional<FileDocument> file = fileService.getById(id);
        if (file.isPresent()) {
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; fileName=" + URLEncoder.encode(file.get().getFileName(), "utf-8"))
                    .header(HttpHeaders.CONTENT_TYPE, "application/octet-stream")
                    .header(HttpHeaders.CONTENT_LENGTH, file.get().getSize() + "")
                    .header("Connection", "close")
                    .body(file.get().getContent());
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(MessageConstant.FILE_NOT_FOUND);
        }
    }

    /**
     * 删除附件

     */

    @ApiOperation(value = "删除文件",notes = "需要管理员账号删除文件，同时会删除文件的包含的页面信息、提取出的图片以及es索引",tags = "admin")
    @SaCheckRole("admin")
    @GetMapping("/delete/{id}")
    public AjaxJson deleteFileByGetMethod(@PathVariable @NotNull String id) {
        Boolean flag = fileService.removeFile(id, true);
        return AjaxJson.getByBoolean(flag,MessageConstant.DELETE_SUCCESS,MessageConstant.DELETE_FAILED);
    }

    @ApiOperation(value = "预览图片",notes = "预览页面缩略图、提取的图片，注意页面的缩略图请传thumbId，提取的图片请传入gridfsId")
    @GetMapping("/thumb/{id}")
    public ResponseEntity<Object> previewThumb(@PathVariable String id)  {
        if (StringUtils.hasText(id)) {
            byte[] bytes = fileService.getFileThumb(id);
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "fileName=" + id)
                    .header(HttpHeaders.CONTENT_TYPE, "image/png")
                    .header(HttpHeaders.CONTENT_LENGTH, bytes.length + "")
                    .body(bytes);
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(MessageConstant.FILE_NOT_FOUND);
        }
    }


    @ApiOperation(value = "重建索引",notes = "如果文件的索引状态不为success，可以通过该接口重建索引，前端注意控制重复点击，重建索引非常耗时")
    @GetMapping("/rebuildIndex")
    public AjaxJson rebuildIndex(@RequestParam("fileId") @NotNull String fileId) {
        return fileService.rebuildIndex(fileId);
    }


    @ApiOperation(value = "将mongo中的数据更新到es中",hidden = true)
    @PostMapping("/updateFileToEs")
    public AjaxJson updateFileToEs(@RequestParam List<String> ids){
        return AjaxJson.getSuccessData(fileService.updateFileToEs(ids));

    }
}
